package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.heart.domain.KingFinancePayRefundDetailEntity;
import com.ly.heart.domain.KingFinancePayRefundEntity;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.refund.PayRefundBo;
import com.ly.heart.domain.king.refund.PayRefundDetailBo;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseError;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingFinancePayRefundDetailService;
import com.ly.heart.service.IKingFinancePayRefundService;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class PayRefundPushService {

    @Resource
    private IKingFinancePayRefundService iKingFinancePayRefundService;
    @Resource
    private IKingFinancePayRefundDetailService iKingFinancePayRefundDetailService;
    @Resource
    private IKingOrgService iKingOrgService;

    public void push (String id) {
        log.info ( "付款退款单推送金蝶，付款退款单Id->{}", id );
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, true ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        K3CloudApi client = new K3CloudApi ( identifyInfo );
        KingFinancePayRefundEntity kingFinancePayRefundEntity = iKingFinancePayRefundService.querySingleById ( id );
        if ( ObjectUtils.isEmpty ( kingFinancePayRefundEntity ) ) {
            throw new CustomException ( "付款退款单对象为空" );
        }
        if ( kingFinancePayRefundEntity.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推送金蝶，无需重复推送！" );
        }
        PayRefundBo bo = assemblePayRefund ( kingFinancePayRefundEntity );
        try {
            save ( bo, client );
            submit ( bo, client );
            audit ( bo, client );
            updateSendSuccess ( kingFinancePayRefundEntity.getId () );
        } catch ( Exception e ) {
            e.printStackTrace ();
        }
    }


    private void save (PayRefundBo payRefundBo, K3CloudApi client) throws Exception {
        KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
        singleRequest.setModel ( payRefundBo );
        String s = JSONObject.toJSONString ( singleRequest );
        log.info ( "付款退款单转JSON->{}", s );
        String resultJson = client.save ( KingConstUtil.AP_REFUNDBILL, s );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "付款退款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.info ( "{} 推送成功", sb );
            //修改状态为已推送

        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "付款退款单-推送失败：【" + sb + "】" );
        }
    }

    private void submit (PayRefundBo payRefundBo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( payRefundBo.getFBillNo () );
        payRefundBo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( payRefundBo );
        String resultJson = client.submit ( KingConstUtil.AP_REFUNDBILL, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "付款退款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 提交成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "付款退款单提交失败：【" + sb + "】" );
        }
    }

    private void audit (PayRefundBo payRefundBo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( payRefundBo.getFBillNo () );
        payRefundBo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( payRefundBo );
        String resultJson = client.audit ( KingConstUtil.AP_REFUNDBILL, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "付款退款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 审核成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "付款退款单审核失败：【" + sb + "】" );
        }
    }

    private void updateSendSuccess (String payRefundId) {
        KingFinancePayRefundEntity payRefundEntity = new KingFinancePayRefundEntity ();
        payRefundEntity.setId ( payRefundId );
        payRefundEntity.setIsSend ( KingConstUtil.KING_DATA_IS_SEND_YES );
        boolean b = iKingFinancePayRefundService.updateById ( payRefundEntity );
        if ( ! b ) {
            throw new CustomException ( "修改推送金蝶状态失败！" );
        }
    }

    /**
     * 组装付款退款单对象
     * @param payRefundEntity
     * @return
     */
    private PayRefundBo assemblePayRefund (KingFinancePayRefundEntity payRefundEntity) {
        PayRefundBo bo = new PayRefundBo ();
        //1.基础
        bo.setFBillNo ( payRefundEntity.getDocNo () );
        //单据类型
        BaseChildBo billType = new BaseChildBo ().setFNumber ( payRefundEntity.getDocTypeCode () );
        bo.setFBillTypeID ( billType );
        //付款单位类型
        bo.setFPAYUNITTYPE ( payRefundEntity.getPayDeptType () );
        //付款组织
        //BaseChildBo payOrg = new BaseChildBo ().setFNumber ( payRefundEntity.getPayDeptId () );
        //付款单位
        BaseChildBo payDept = new BaseChildBo ().setFNumber ( payRefundEntity.getPayCompanyCode () );
        bo.setFPAYUNIT ( payDept );
        //结算组织
        //业务日期
        bo.setFDATE ( CommonUtil.getDateStrFormat ( payRefundEntity.getBusinessTime (), "yyyy-MM-dd HH:mm:ss" ) );
        //币别
        BaseChildBo currency = new BaseChildBo ().setFNumber ( payRefundEntity.getCurrencyCode () );
        bo.setFCURRENCYID ( currency );
        //往来单位类型
        bo.setFCONTACTUNITTYPE ( payRefundEntity.getTransactionCompanyType () );
        //采购部门
        BaseChildBo purchaseDept = new BaseChildBo ().setFNumber ( payRefundEntity.getPruDeptCode () );
        bo.setFPurchaseDeptId ( purchaseDept );
        //往来单位
        BaseChildBo transactionCompanyCode = new BaseChildBo ().setFNumber ( payRefundEntity.getTransactionCompanyCode () );
        bo.setFCONTACTUNIT ( transactionCompanyCode );
        //采购员
        BaseChildBo purUser = new BaseChildBo ().setFNumber ( payRefundEntity.getPurUserCode () );
        bo.setFPurchaserId ( purUser );
        //备注
        bo.setFREMARK ( payRefundEntity.getRemarks () );
        //退款单明细行
        List<PayRefundDetailBo> payRefundDetailBos = assemblePayRefundDetailBos ( payRefundEntity.getId () );
        bo.setFREFUNDBILLENTRY ( payRefundDetailBos );
        return bo;
    }

    /**
     * 组装付款退款明细行列表
     * @return
     */
    private List<PayRefundDetailBo> assemblePayRefundDetailBos (String payRefundId) {
        List<KingFinancePayRefundDetailEntity> list = iKingFinancePayRefundDetailService.list ( new LambdaQueryWrapper<KingFinancePayRefundDetailEntity> ().
                eq ( KingFinancePayRefundDetailEntity :: getPayRefundId, payRefundId ) );
        List<PayRefundDetailBo> payRefundDetailBos = new ArrayList<> ();
        list.forEach ( detail -> {
            PayRefundDetailBo bo = new PayRefundDetailBo ();
            //
            //结算方式
            BaseChildBo settleType = new BaseChildBo ().setFNumber ( detail.getKingSettlementTypeCode () );
            bo.setFSETTLETYPEID ( settleType );
            //原付款用途
            BaseChildBo payPurposeCode = new BaseChildBo ().setFNumber ( detail.getPayPurposeCode () );
            bo.setFPURPOSEID ( payPurposeCode );
            //应退金额
            bo.setFREFUNDAMOUNTFOR ( detail.getCopeRefundMoney () );
            //手续费
            bo.setFHANDLINGCHARGEFOR ( detail.getHandlingFees () );
            //现金折扣
            bo.setFDISTAMOUNTFOR ( detail.getCashDiscount () );
            //长短款
            bo.setFOUAMOUNTFOR ( detail.getLongShortPay () );
            //我方银行账号
            BaseChildBo account = new BaseChildBo ().setFNumber ( detail.getBankNumber () );
            bo.setFACCOUNTID ( account );
            //现金账号
            //BaseChildBo cashAccount = new BaseChildBo ().setFNumber ( detail.getBankNumber () );

            //结算号
            bo.setFSETTLENO ( detail.getSettlementNumber () );
            //备注
            bo.setFNOTE ( detail.getRemarks () );
            //费用项目
            BaseChildBo fee = new BaseChildBo ().setFNumber ( detail.getFeeCode () );
            bo.setFCOSTID ( fee );
            //费用承担部门
            BaseChildBo feeBearDeptCode = new BaseChildBo ().setFNumber ( detail.getFeeBearDeptCode () );
            bo.setFEXPENSEDEPTID_E ( feeBearDeptCode );
            //含税单价
            bo.setFPRICE ( detail.getTaxPrice () );
            //数量
            bo.setFQTY ( detail.getNum () );
            //采购订单编号
            bo.setFPURCHASEORDERNUMBER ( detail.getOrderNo () );
            payRefundDetailBos.add ( bo );
        } );
        return payRefundDetailBos;
    }

}
